package cn.mumzone.basic.base;

import android.app.Activity;
import android.app.Dialog;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.util.DisplayMetrics;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
import android.widget.EditText;


import java.lang.ref.WeakReference;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Stack;

import butterknife.ButterKnife;
import butterknife.Unbinder;
import cn.mumzone.basic.R;
import cn.mumzone.basic.dialog.AlertDialog;
import cn.mumzone.basic.loading.dialog.LoadingDialog;
import cn.mumzone.basic.loading.dialog.VaryViewHelperController;
import cn.mumzone.basic.mvp.BasePresenter;
import cn.mumzone.basic.mvp.BaseView;
import cn.mumzone.basic.netstatus.NetChangeObserver;
import cn.mumzone.basic.netstatus.NetStateReceiver;
import cn.mumzone.basic.netstatus.NetUtils;
import cn.mumzone.basic.util.IsFastClickUtil;
import cn.mumzone.basic.util.PosToast;
import cn.mumzone.basic.util.ToastUtil;
import cn.mumzone.basic.util.log.Elog;

/**
 * Author Chaney
 * Date   2017/3/7 上午10:13.
 * EMail  qiuzhenhuan.hi@gmail.com
 */

public abstract class BaseActivity<T extends BasePresenter> extends AppCompatActivity implements BaseView {

    protected int mScreenWidth = 0;
    protected int mScreenHeight = 0;
    protected float mScreenDensity = 0.0f;

    protected T mPresenter;
    protected Activity mContext;
    private Unbinder mUnbinder;
    public MyHandler mHandler = new MyHandler(this);
    private VaryViewHelperController mVaryViewHelperController = null;
    private Stack<LoadingDialog> mDialogStack = new Stack<>();
    private String codeStr = "";

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initPresenter();

        if (isForcePortrait()) {
            setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
        }

        if (toggleOverridePendingTransition()) {
            overridePendingTransition(R.anim.right_in, R.anim.exit_trans);
        }

        Bundle extras = getIntent().getExtras();
        if (null != extras) {
            getBundleExtras(extras);
        }

        DisplayMetrics displayMetrics = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);

        mScreenDensity = displayMetrics.density;
        mScreenHeight = displayMetrics.heightPixels;
        mScreenWidth = displayMetrics.widthPixels;

        if (getLayout() != 0) {
            setContentView(getLayout());
        } else {
            throw new IllegalArgumentException("You must return a right contentView layout resource Id");
        }

        if (null != getTargetView()) {
            mVaryViewHelperController = new VaryViewHelperController(getTargetView());
        }


        addToTask();

        initVariable();

        initEventAndData();

        if (!NetUtils.isNetworkAvailable(this)) {
            if (getTargetView() != null) {
                showNetErrorEmpty(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        if (!NetUtils.isNetworkConnected(mContext)) {
                            PosToast.INSTANCE.makeShortToast(mContext, "网络不给力，请稍后再试");
                            return;
                        }
                        if (getTargetView() != null) toggleCloseEmpty();
                        refreshNetwork();
                    }
                });
            }
        }

    }

    @Override
    public void setContentView(int layoutResID) {
        super.setContentView(layoutResID);
        mUnbinder = ButterKnife.bind(this);
        mContext = this;
    }

    /**
     * 获取 Presenter 泛型实例
     */
    private void initPresenter() {
        Type type = getClass().getGenericSuperclass();
        if (type instanceof ParameterizedType) {
            Type[] types = ((ParameterizedType) type).getActualTypeArguments();
            Class<T> presenterClass = (Class<T>) types[0];
            try {
                mPresenter = presenterClass.newInstance();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        if (mPresenter != null) {
            mPresenter.attachView(this);
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        mHandler.removeCallbacksAndMessages(null);
        if (mPresenter != null) {
            mPresenter.detachView();
        }
        if (mUnbinder != null && mUnbinder != Unbinder.EMPTY) {
            mUnbinder.unbind();
        }
        closeAllLoadingDialog();
    }

    private void closeAllLoadingDialog() {
        if (!mDialogStack.isEmpty()) {
            while (!mDialogStack.isEmpty()) {
                LoadingDialog dialog = mDialogStack.pop();
                dialog.dismiss();
            }
        }
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);

    }

    @Override
    public void showLoadingDialog() {
        LoadingDialog dialog = new LoadingDialog.Builder(mContext)
                .setMessage("正在加载中...")
                .setCancelable(false)
                .create();
        dialog.show();
        mDialogStack.push(dialog);
    }

    @Override
    public void dismissLoadingDialog() {
        if (!mDialogStack.isEmpty()) {
            LoadingDialog dialog = mDialogStack.pop();
            dialog.dismiss();
        }
    }

    protected void toggleShowEmpty(boolean toggle, int img, String msg, String emptyGoText, View.OnClickListener onClickListener) {
        if (null == mVaryViewHelperController) {
            throw new IllegalArgumentException("You must return a right target view for loading");
        }

        if (toggle) {
            mVaryViewHelperController.showEmpty(img, msg, emptyGoText, onClickListener);
        } else {
            mVaryViewHelperController.restore();
        }
    }

    protected void toggleCloseEmpty() {
        if (null == mVaryViewHelperController) {
            throw new IllegalArgumentException("You must return a right target view for loading");
        }
        mVaryViewHelperController.restore();
    }

    protected void toggleShowEmpty(boolean toggle, int img, String msg, String secondeMsg) {
        if (null == mVaryViewHelperController) {
            throw new IllegalArgumentException("You must return a right target view for loading");
        }

        if (toggle) {
            mVaryViewHelperController.showEmpty(img, msg, secondeMsg);
        } else {
            mVaryViewHelperController.restore();
        }
    }

    protected void toggleShowEmpty(boolean toggle) {
        this.toggleShowEmpty(toggle, -1, "", "", null);
    }

    protected void showNetErrorEmpty() {
        if (null == mVaryViewHelperController) {
            throw new IllegalArgumentException("You must return a right target view for loading");
        }

        mVaryViewHelperController.showNetError(false, null);
    }

    protected void showNetErrorEmpty(View.OnClickListener onClickListener) {
        if (null == mVaryViewHelperController) {
            throw new IllegalArgumentException("You must return a right target view for loading");
        }
        mVaryViewHelperController.showNetError(true, onClickListener);
    }

    /**
     * startActivity with bundle
     *
     * @param clazz
     * @param bundle
     */
    protected void readyGo(Class<?> clazz, Bundle bundle) {
        Intent intent = new Intent(this, clazz);
        if (null != bundle) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
    }

    /**
     * startActivity then finish
     *
     * @param clazz
     */
    protected void readyGoThenKill(Class<?> clazz) {
        Intent intent = new Intent(this, clazz);
        startActivity(intent);
        finish();
    }

    /**
     * startActivity with bundle then finish
     *
     * @param clazz
     * @param bundle
     */
    protected void readyGoThenKill(Class<?> clazz, Bundle bundle) {
        Intent intent = new Intent(this, clazz);
        if (null != bundle) {
            intent.putExtras(bundle);
        }
        startActivity(intent);
        finish();
    }

    /**
     * startActivityForResult
     *
     * @param clazz
     * @param requestCode
     */
    protected void readyGoForResult(Class<?> clazz, int requestCode) {
        Intent intent = new Intent(this, clazz);
        startActivityForResult(intent, requestCode);
    }

    /**
     * startActivityForResult with bundle
     *
     * @param clazz
     * @param requestCode
     * @param bundle
     */
    protected void readyGoForResult(Class<?> clazz, int requestCode, Bundle bundle) {
        Intent intent = new Intent(this, clazz);
        if (null != bundle) {
            intent.putExtras(bundle);
        }
        startActivityForResult(intent, requestCode);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        List<Fragment> fragments = getSupportFragmentManager().getFragments();
        if (fragments != null && !fragments.isEmpty()) {
            for (Fragment fragment : fragments) {
                fragment.onActivityResult(requestCode, resultCode, data);
            }
        }
    }

    @Override
    public void finish() {
        super.finish();
        ActivityTaskManager.getInstance().removeActivity(this.getClass().getName());
        if (toggleOverridePendingTransition()) {
            overridePendingTransition(0, R.anim.right_out);
        }
    }

    /**
     * 返回键，关闭aty
     *
     * @param view
     */
    public void onActionFinish(View view) {
        finish();
    }

    /**
     * 把当前Activity添加到activityMap统一管理
     */
    protected void addToTask() {
        ActivityTaskManager.getInstance().putActivity(this.getClass().getName(), this);
    }

    /**
     * 初始化 AlertDialog 的封装方法
     *
     * @param contentViewId
     * @param listener
     * @param clickViews
     * @return
     */
    protected AlertDialog initAlertDialog(int contentViewId, View.OnClickListener listener, int... clickViews) {
        AlertDialog alertDialog = new AlertDialog.Builder(mContext)
                .setContentView(contentViewId)
                .setCancelableOntheOutside(false)
                .setWidthAndHeight(700, 400)
                .create();
        if (listener != null) {
            for (int i = 0; i < clickViews.length; i++) {
                alertDialog.setOnClickListener(clickViews[i], listener);
            }
        }
        return alertDialog;
    }

    protected AlertDialog initAlertDialog(int contentViewId, int width, int height, View.OnClickListener listener, int... clickViews) {
        AlertDialog alertDialog = new AlertDialog.Builder(mContext)
                .setContentView(contentViewId)
                .setCancelableOntheOutside(false)
                .setWidthAndHeight(width, height)
                .create();
        if (listener != null) {
            for (int i = 0; i < clickViews.length; i++) {
                alertDialog.setOnClickListener(clickViews[i], listener);
            }
        }
        return alertDialog;
    }

    /**
     * 使用软引用的 Handler
     * 避免不当操作导致的内存泄漏
     */
    public static class MyHandler extends Handler {
        private WeakReference<BaseActivity> mActivity;

        public MyHandler(BaseActivity activity) {
            mActivity = new WeakReference<>(activity);
        }

        @Override
        public void handleMessage(Message msg) {
            if (mActivity.get() != null) {
                mActivity.get().handleMsg(msg);
            }
        }
    }

    protected void closeDialog(Dialog... dialogArray) {
        for (Dialog dialog : dialogArray) {
            if (dialog != null && dialog.isShowing()) {
                dialog.dismiss();
            }
        }
    }

    protected void showDialog(Dialog dialog) {
        if (dialog != null && !dialog.isShowing()) {
            dialog.show();
        }
    }

    protected View getTargetView() {
        return null;
    }

    public void showError(String msg) {
        PosToast.INSTANCE.makeShortToast(mContext, msg + "~");
    }

    @Override
    public void showNetError() {
        if (getTargetView() != null) {
            showNetErrorEmpty(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (!NetUtils.isNetworkConnected(mContext)) {
                        PosToast.INSTANCE.makeShortToast(mContext, "网络不给力，请稍后再试");
                        return;
                    }
                    if (getTargetView() != null) toggleCloseEmpty();
                    refreshNetwork();
                }
            });
        }
    }

    protected void handleMsg(Message msg) {
    }

    protected void getBundleExtras(Bundle extras) {
    }

    protected void refreshNetwork() {
    }

    protected boolean isForcePortrait() {
        return true;
    }

    protected boolean toggleOverridePendingTransition() {
        return true;
    }

    protected void initVariable() {
    }

    protected abstract void initEventAndData();

    protected abstract int getLayout();

    protected void onNetworkConnected(NetUtils.NetType type) {
        showNetErrorEmpty();
    }

    protected void onNetworkDisConnected() {
        toggleCloseEmpty();
    }

    /**
     * 解决了EditText弹出软键盘关闭不了的问题
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            View v = getCurrentFocus();
            if (isShouldHideInput(v, ev)) {

                InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
                if (imm != null) {
                    imm.hideSoftInputFromWindow(v.getWindowToken(), 0);
                }
            }
            return super.dispatchTouchEvent(ev);
        }
        // 必不可少，否则所有的组件都不会有TouchEvent了
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

    public boolean isShouldHideInput(View v, MotionEvent event) {
        if (v != null && (v instanceof EditText)) {
            int[] leftTop = {0, 0};
            // 获取输入框当前的location位置
            v.getLocationInWindow(leftTop);
            int left = leftTop[0];
            int top = leftTop[1];
            int bottom = top + v.getHeight();
            int right = left + v.getWidth();
            if (event.getX() > left && event.getX() < right && event.getY() > top && event.getY() < bottom) {
                // 点击的是输入框区域，保留点击EditText的事件
                return false;
            } else {
                return true;
            }
        }
        return false;
    }

    /**
     * 隐藏Android底部的虚拟按键
     */
    private void hideVirtualKey() {
        Window window = getWindow();
        WindowManager.LayoutParams params = window.getAttributes();
        params.systemUiVisibility = View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
        window.setAttributes(params);
    }

    public void setViewVisibility(View view, boolean v_or_gone) {
        if (view == null) {
            ToastUtil.debugToast(this, "You must keep the view not null", false);
            return;
        }
        view.setVisibility(v_or_gone ? View.VISIBLE : View.GONE);
    }

    public void setViewVisibility(View view, int visibility) {
        if (view == null) {
            ToastUtil.debugToast(this, "You must keep the view not null", false);
            return;
        }
        view.setVisibility(visibility);
    }

//    @Override
//    public boolean dispatchKeyEvent(KeyEvent event) {
//
//        if (event.getDeviceId() == -1) {
//            return false;
//        }
//        if (event.getAction() == KeyEvent.ACTION_UP) {
//
//            int code = event.getKeyCode();
//            if (code >= KeyEvent.KEYCODE_0 && code <= KeyEvent.KEYCODE_9) {
//                codeStr += (code - KeyEvent.KEYCODE_0);
//            }
//
//            if (code == KeyEvent.KEYCODE_ENTER) {
//                onScanCodeInput(codeStr);
//                codeStr = "";
//            }
//
//        }
//        return super.dispatchKeyEvent(event);
//    }

    protected void onScanCodeInput(String scanCode) {

    }
}
